package com.passer.uam.password;


import com.passer.toolbox.common.file.constant.FileConstants;
import com.passer.toolbox.common.core.util.DateUtils;
import com.passer.toolbox.common.core.util.StringUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Data
public class PasswordGeneration {

    private String passwordFilePath;

    public PasswordGeneration(String passwordFilePath) {
        File folder = new File(passwordFilePath, new Date().getTime() + "");
        if (!folder.mkdirs()) {
            throw new RuntimeException(folder.getAbsolutePath() + "创建失败");
        }
        this.passwordFilePath = folder.getAbsolutePath();
    }

    public void generationPasswordByFile(String passwordChars, int passwordNum) {
        String[] chars = passwordChars.split("");
        List<String> charList = Arrays.asList(chars);
        String firstChars = joinFirstChar(charList.get(0), passwordNum, 0);
        File folder = new File(this.passwordFilePath, "0");
        if (!folder.mkdirs()) {
            throw new RuntimeException(folder.getAbsolutePath() + "创建失败");
        }
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(folder, "0-0-0.txt"), true))) {
            for (String aChar : chars) {
                writer.write(aChar + firstChars + '\n');
            }
            writer.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        for (int i = 1; i < passwordNum; i++) {
            generationPasswordByFile(charList, passwordNum, i);
        }
    }

    private void generationPasswordByFile(List<String> charList, int passwordNum, int currentNum) {
        Date start = new Date();
        log.info("生成第{}类密码-开始", currentNum);
        int perNum = currentNum - 1;
        File folder = new File(this.passwordFilePath, perNum + "");
        File[] files = folder.listFiles();
        if (files == null || files.length == 0) {
            return;
        }
        File currentFolder = new File(this.passwordFilePath, currentNum + "");
        if (!currentFolder.mkdirs()) {
            throw new RuntimeException(currentFolder.getAbsolutePath() + "创建失败");
        }
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(6, passwordNum, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        String firstChars = joinFirstChar(charList.get(0), passwordNum, currentNum);
        for (File file : files) {
            threadPoolExecutor.execute(() -> generationPasswordByFile(file, currentFolder, charList, currentNum, firstChars));
        }
        threadPoolExecutor.shutdown();
        try {
            if (!threadPoolExecutor.awaitTermination(2, TimeUnit.HOURS)) {
                log.error("【PasswordGeneration】线程池等待失败，停止所有线程");
                threadPoolExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            log.error("【PasswordGeneration】线程池等待异常：{}", e.getMessage());
            threadPoolExecutor.shutdownNow();
        }
        List<File> sFiles = Arrays.stream(files).filter(file -> file.getName().startsWith(perNum + "-s-s-")).collect(Collectors.toList());
        for (File sFile : sFiles) {
            if (sFile.exists() && !sFile.delete()) {
                log.error("{}删除失败", sFile.getName());
            }
        }
        Date end = new Date();
        log.info("生成第{}类密码-结束,耗时：{}", currentNum, DateUtils.formatMillis(end.getTime() - start.getTime()));
    }

    private void generationPasswordByFile(File file, File currentFolder, List<String> charList, int currentNum, String firstChars) {
        String[] nameSplit = file.getName().replace(".txt", "").split("-");
        int fileNum = 0;
        String line;
        try (
                BufferedReader reader = new BufferedReader(new FileReader(file))
        ) {
            while (fileNum > -1) {
                try (
                        BufferedWriter writer = new BufferedWriter(new FileWriter(new File(currentFolder, currentNum + "-" + nameSplit[2] + "-" + fileNum++ + ".txt"), true));
                        BufferedWriter writer0 = new BufferedWriter(new FileWriter(new File(currentFolder, currentNum + "-s-s-" + fileNum++ + ".txt"), true))
                ) {
                    for (int i = 0; i < 100; i++) {
                        line = reader.readLine();
                        if (StringUtils.isEmpty(line)) {
                            fileNum = -1;
                            break;
                        }
                        line = line.substring(0, currentNum);
                        writer0.write(line + charList.get(0) + firstChars + "\n");
                        writer0.flush();
                        for (int j = 1; j < charList.size(); j++) {
                            writer.write(line + charList.get(j) + firstChars + "\n");
                        }
                        writer.flush();
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


    }

    public void generationPassword(String passwordChars, int passwordNum) {
        String[] chars = passwordChars.split("");
        List<String> charList = Arrays.asList(chars);
        for (int i = 0; i < chars.length; i++) {
            generationPassword(charList, passwordNum, i);
        }
    }

    public void generationPassword(List<String> charList, int passwordNum, int currentNum) {
        int size = charList.size();
        String firstChars = joinFirstChar(charList.get(0), passwordNum, currentNum);
        List<String> perList = new ArrayList<>();
        List<String> list = new ArrayList<>(charList);
        for (int j = 0; j <= currentNum; j++) {
            int k = j == currentNum ? 1 : 0;
            for (; k < size; k++) {
                for (String s : perList) {
                    list.add(s + charList.get(k));
                }
            }
            perList.clear();
            perList.addAll(list);
            list.clear();
        }
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(this.passwordFilePath, currentNum + ".txt"), true))) {
            for (String s : perList) {
                writer.write(s + firstChars + '\n');
            }
            writer.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void generationPassword(char[] chars, int passwordNum, int currentNum) {
        int size = chars.length;
        int pow = (int) Math.pow(size, passwordNum - 1);
        int[] indexArray = new int[currentNum];
        String firstChars = joinFirstChar(String.valueOf(chars[0]), passwordNum, currentNum);
        StringBuilder passwordBuilder = new StringBuilder();
        int fileNum = 0;
        int maxLine = Math.min(pow, FileConstants.TEXT_FILE_MAX_LINE);
        int currentLine = 0;
        int power;
        // for (int i = 0; i <= pow; i++) {
        //     for (int j = 1; j < passwordNum - 1; j++) {
        //         if ()
        //     }
        // }

        // int i = 1;
        // while (i < pow) {
        //     try (
        //             BufferedWriter writer = new BufferedWriter(new FileWriter(new File(this.passwordFilePath, currentNum + "-" + fileNum++ + ".txt"), true))
        //     ) {
        //         for (; i < maxLine; i++) {
        //             for (int j = 1; j < size; j++) {
        //
        //             }
        //             for (int j = 1; j < passwordNum; j++) {
        //                 if (Math.pow(size, j) > i && Math.pow(size, j - 1) <= i) {
        //                     if (i == Math.pow(size, j - 1)) {
        //
        //                     }
        //                     indexArray[j - 1] = indexArray[j - 1] + 1;
        //                     break;
        //                 }
        //             }
        //             for (int index : indexArray) {
        //                 passwordBuilder.append(chars[index]);
        //             }
        //             passwordBuilder.append('\n');
        //             writer.write(passwordBuilder.toString());
        //         }
        //         writer.flush();
        //
        //     } catch (IOException e) {
        //         throw new RuntimeException(e);
        //     }
        // }

    }

    private String joinFirstChar(String charStr, int passwordNum, int num) {
        StringBuilder builder = new StringBuilder();
        int sub = passwordNum - num - 1;
        for (int j = 0; j < sub; j++) {
            builder.append(charStr);
        }
        return builder.toString();
    }

}
